/**
 * Created by macos on 14/11/11.
 */

(function(){
  var root = this;
  var AccessTokenController = {};

  function validateUser(next) {
    var reqJson = root.request;
    User.findOne({username:reqJson.username, password:reqJson.password})
      .exec(function(err, result) {
        //...
        if(err){
            sails.log.error(err);
            return next(err);
        }
        if(_.has(result,"id")){
            delete root.request.password;
            root.request.userId = result.id;
            return next();
        }else {
            err = new Error();
            err.message = 'user not found!';
            err.status = 404;
            return next(err);
        }
      });
  }

  function validateRefreshToken(next){
      var token = {refreshToken:null};
      if (_.has(root.request, 'refreshToken')) {
          token.refreshToken = root.request.refreshToken;
      }
      RefreshToken.findOne(token).
          exec(function(err,result){
              if(err){
                  return next(err);
              };
              if(_.has(result,"id")){
                  root.request.userId = result.userId;
                  root.request.username = result.username;
                  next();
              }else{
                  err = new Error();
                  err.message = 'refreshToken is not exist!';
                  err.status = 404;

                  return next(err);
              }
          })
  }

  function createRefreshToken(next) {
      var reqJson = root.request;
      var timestamp =reqJson.timestamp;
      var authorization =reqJson.authorization;

          RefreshToken.create(reqJson)
          .exec(function(err, result){
              //..
              if(err){
                  sails.log.error(err);
                  return next(err);
              }
              reqJson.timestamp  = timestamp;
              reqJson.authorization  = authorization;
              reqJson.refreshToken = result.refreshToken;
              next();
          })
  }

  function createAccessToken(next) {
    var reqJson = root.request;

//    AccessToken.checkTTL();

    AccessToken.create(reqJson)
      .exec(function(err, result){
        //..
        if(err){
            sails.log.error(err);
            return next(err);
        }
        next(null, result);
      })

  }

  function validateCode(next){
      var reqJson = root.request;
      var code = reqJson.code;
      var serviceName = reqJson.serviceName;
      Authorization.findOne({serviceName:serviceName, code:code})
          .exec(function(err, result) {
              //...
              if(err){
                  sails.log.error(err);
                  return next(err);
              }
              if(_.has(result,"id")){
                  if(!result.checkTTL()){
                      return next("code is expired")
                  }
                  delete root.request.code;
                  root.request.userId = result.userId;
                  root.request.username = result.username;
                  return next();
              }else {
                  err = new Error();
                  err.message = 'code not exist!';
                  err.status = 404;
                  return next(err);
              }
          });
  }
  function validateAccessToken(next){
      var token = root.request.validateToken;
      AccessToken.findOne({accessToken:token})
          .exec(function(err, result) {
              if (err){
                  sails.log.error(err);
                  return next(err);
              }
              else if (!result) {
                  return  next('validateToken not found or expired');
              }
              else if (!result.checkTTL()) {
                  return  next('validateToken already expired');
              }
              else {
                  return next();
              };
          });
  }

  AccessTokenController.index = function(req, res) {
    root.request = req.body;

    if (root.request.grantType === 'password') {
      async.waterfall([
        validateUser,
        createRefreshToken,
        createAccessToken
      ], function(err, result) {
        if (err) {

          if (_.has(err, 'status')) {
            return res.jsonResponse(err.status, err.message);
          } else {
            return res.jsonResponse(403, err);
          }
        }

        var token = {
            "access_token":result.accessToken,
            "token_type":result.tokenType,
            "expires_in":result.expiresTime-new Date().getTime(),
            "refresh_token":result.refreshToken
        };
        return res.jsonResponse(200, token);

      })

    } else if (root.request.grantType === 'refresh_token') {
      //...
        async.waterfall([
            validateRefreshToken,
            createAccessToken
        ], function(err, result) {
            if (err) {

                if (_.has(err, 'status')) {
                    return res.jsonResponse(err.status, err.message);
                } else {
                    return res.jsonResponse(403, err);
                }
            }
            var token = {
                "access_token":result.accessToken,
                "token_type":result.tokenType,
               /* "refresh_token":result.refreshToken,*/
                "expires_in":result.expiresTime-new Date().getTime()
            };
            return res.jsonResponse(200, token);

        })

    } else if (root.request.grantType === 'client_credentials') {
      //...
        async.waterfall([
            createAccessToken
        ], function(err, result) {
            if (err) {

                if (_.has(err, 'status')) {
                    return res.jsonResponse(err.status, err.message);
                } else {
                    return res.jsonResponse(403, err);
                }
            }
            var token = {
                "access_token":result.accessToken,
                "token_type":result.tokenType,
                "expires_in":result.expiresTime-new Date().getTime()
            };
            return res.jsonResponse(200, token);

        })
    }  else if (root.request.grantType === 'code') {
      //...
        async.waterfall([
            validateCode,
            createRefreshToken,
            createAccessToken
        ], function(err, result) {
            if (err) {

                if (_.has(err, 'status')) {
                    return res.jsonResponse(err.status, err.message);
                } else {
                    return res.jsonResponse(403, err);
                }
            }
            var token = {
                "access_token":result.accessToken,
                "token_type":result.tokenType,
                "refresh_token":result.refreshToken,
                "expires_in":result.expiresTime-new Date().getTime()
            };
            return res.jsonResponse(200, token);

        })
    }

    else {
      return res.jsonResponse(404, "grantType not found!");
    }
  }

    AccessTokenController.validateToken = function(req, res) {
        root.request = req.body;

        async.waterfall([
            validateAccessToken
        ], function(err, result) {
            if (err) {

                if (_.has(err, 'status')) {
                    return res.jsonResponse(err.status, err.message);
                } else {
                    return res.jsonResponse(403, err);
                }
            }
            return res.jsonResponse(200, "validateToken validation passed");

        })
    }



  module.exports = AccessTokenController;
})();

